﻿#include "DBService.h"
#include "DataPackage.h"

#include <QSqlError>
#include <QSqlQuery>
#include <QSqlDriver>
#include <QSettings>
#include <QSqlRecord>
#include <QJsonDocument>
#include <QCoreApplication>
#include "OutPutMessage.h"

#ifdef Q_OS_LINUX
#include <QPluginLoader>
#endif // DEBUG


int QDBService::iDbCount = 0;

QDBService::QDBService(QObject *parent)
: QObject(parent)
{

}

QDBService::~QDBService()
{

}

/***********************************************************************************************************************************/
bool QDBService::init()
{
	QString appFile = QCoreApplication::applicationDirPath() + "/" + QCoreApplication::applicationName() + ".ini";
	QSettings config(appFile, QSettings::IniFormat);

	config.beginGroup("DB");
	DBConnection stConnection;
	stConnection.strName = config.value("Name", "DBName").toString() + QString("%1").arg(++iDbCount);
	stConnection.strType = config.value("Type", "QODBC").toString();
	stConnection.strScheme = config.value("Scheme", "").toString();
	stConnection.iHostPort = config.value("HostPort", "8080").toInt();
	stConnection.strHostName = config.value("HostName", "127.0.0.1").toString();
	stConnection.strUserName = config.value("UserName", "").toString();
	stConnection.strPassword = config.value("Password", "").toString();
	config.endGroup();

	if (stConnection.strScheme.isEmpty())
	{
		outPutMessage(tr("database config is null"), MSG_ERROR);
		return false;
	}

	return initDatabase(stConnection);
}

bool QDBService::initDatabase(const DBConnection & stConnect)
{
	if (QSqlDatabase::contains(stConnect.strName))
	{
		db = QSqlDatabase::database(stConnect.strName);
		if (db.open())
			db.close();
		QSqlDatabase::removeDatabase(stConnect.strName);
	}

	db = QSqlDatabase::addDatabase(stConnect.strType, stConnect.strName);
	if (db.isValid())
	{
		db.setHostName(stConnect.strHostName);
		db.setPort(stConnect.iHostPort);
		db.setUserName(stConnect.strUserName);
		db.setPassword(stConnect.strPassword);
		db.setDatabaseName(stConnect.strScheme);

		if (db.open())
		{
			outPutMessage(tr("Connect Database Success"));
			return true;
		}
	}

#ifdef Q_OS_LINUX
	QPluginLoader loader;
	// MySQL 驱动插件的路径
	QString strFile;
	if (stConnect.strType == "QODBC")
		strFile = QCoreApplication::applicationDirPath() + "/plugins/sqldrivers/libqsqlodbc.so";
	loader.setFileName(strFile);
	if (loader.load() == false)
	{
		outPutMessage(loader.errorString(), MSG_ERROR);
	}

#endif

	QString strMsg = tr("Connect Database Error: ") + db.lastError().text();
	outPutMessage(strMsg, MSG_ERROR);

	QSqlDatabase::removeDatabase(stConnect.strName);
	return false;
}

/***********************************************************************************************************************************/

QSqlQuery * QDBService::select(const QString & SQL, bool & bExec)
{
	if (db.isOpen() == false)
	{
		outPutMessage(tr("Database is not connect"), MSG_ERROR);
		return NULL;
	}

	QSqlQuery * query = new QSqlQuery(db);
	bExec = query->exec(SQL);
	return query;
}

bool QDBService::execSQL(const QString & SQL, QString & strMsg)
{
	if (db.isOpen() == false)
	{
		strMsg = tr("Database is not connect");
		outPutMessage(strMsg, MSG_ERROR);
		return false;
	}

	QSqlQuery query(db);
	QString strSQL = SQL;
	strSQL.append(";");
	bool bExec = query.exec(SQL);
	if (bExec)
	{
		int count = query.numRowsAffected();
		strMsg = tr("Rows: %1 affected!").arg(count);
		outPutMessage(tr("Exec SQL : %1 ").arg(SQL) + strMsg);
		return true;
	}
	else
	{
		strMsg = tr("exec SQL failed , \n SQL: %1 \n Error: %2").arg(SQL).arg(query.lastError().text());
		outPutMessage(strMsg, MSG_ERROR);
		return false;
	}
}

bool QDBService::execBatch(const QVariantList & listSQL, QString & strMsg)
{
	QString strTemp;

	if (QSqlDatabase::database().driver()->hasFeature(QSqlDriver::Transactions))
	{ 
		if (QSqlDatabase::database().transaction())
		{
			bool bExec = false;
			for (int i = 0; i < listSQL.count(); ++i)
			{
				if (!execSQL(listSQL.at(i).toString(), strTemp))
				{
					strMsg.append(QString("%1: %2 \n").arg(i).arg(strTemp));
					bExec = false;
					break;
				}

				strMsg.append(QString("%1: %2 \n").arg(i).arg(strTemp));
			}

			if (bExec && QSqlDatabase::database().commit())
			{
				return true;
			}
			else
			{
				strMsg.append(QSqlDatabase::database().lastError().text());
				QSqlDatabase::database().rollback();
				return false;
			}
		}
	}
	else
	{
		for (int i = 0; i < listSQL.count(); ++i)
		{
			if (!execSQL(listSQL.at(i).toString(), strTemp))
			{
				strMsg.append(QString("%1: %2 \n").arg(i).arg(strTemp));
				return false;
			}

			strMsg.append(QString("%1: %2 \n").arg(i).arg(strTemp));
		}
	}
	return true;
}